package com.xlongwei.accounts.service;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.noear.solon.Solon;
import org.noear.solon.Utils;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.handle.Context;
import org.smartboot.http.common.utils.NumberUtils;

import com.xlongwei.accounts.config.AppConfig;
import com.xlongwei.accounts.config.DsConfig;
import com.xlongwei.accounts.config.MySqlUtils;
import com.xlongwei.accounts.controller.UserController;
import com.xlongwei.accounts.dao.VipDao;
import com.xlongwei.accounts.model.User;
import com.xlongwei.accounts.model.Vip;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class VipService {
    static final boolean enableVip =
            "true".equalsIgnoreCase(Solon.cfg().get("vip.enable", "false"));
    static final int daysVip = NumberUtils.toInt(Solon.cfg().get("vip.days"), 31);
    @Inject
    VipDao vipDao;

    public VipService() {
        log.info("vip.enable={} vip.ds={} vip.days={}", enableVip, VipDao.dsName, daysVip);
    }

    public Vip vip(String mobileDs, boolean newUser) {
        return vip(mobileDs, newUser, newUser ? LocalDate.now() : null);
    }

    public Vip vip(String mobileDs, boolean newUser, LocalDate regDay) {
        if (enableVip == false) {
            return null;
        }
        log.info("mobileDs={} newUser={} regDay={}", mobileDs, newUser, regDay);
        Long mobileL = Long.parseLong(mobileDs.substring(0, 11));
        Vip vip = vipDao.findByMobile(mobileL).stream()
                .filter(e -> e.getMobileDs().equals(mobileDs)).findAny().orElse(null);
        if (newUser && vip == null) {
            vip = new Vip();
            vip.setMobileDs(mobileDs);
            vip.setRegDay(regDay != null ? regDay : LocalDate.now());
            vip.setVipDay(vip.getRegDay().plusYears(1));
            Integer id = vipDao.create(vip);
            log.info("id={}", id);
        }
        return vip;
    }

    public void set(User user, Vip vip, LocalDate now) {
        boolean showDays = false;
        long days = 0;
        if (vip != null && vip.getVipDay() != null) {
            days = now.until(vip.getVipDay(), ChronoUnit.DAYS);
            showDays = days <= daysVip;
        }
        log.info("showDays={} user={} vip={} now={} vipDay={} days={}", showDays, user.getMobile(),
                vip == null ? null : vip.getMobileDs(), now, vip == null ? null : vip.getVipDay(),
                days);
        if (showDays) {
            user.setVipDay(vip.getVipDay());
        } else {
            user.setVipDay(null);
        }
    }

    public void set(User user) {
        LocalDate day = null;
        try {
            String now = Context.current().param("now");
            if (Utils.isNotBlank(now)) {
                day = LocalDate.parse(now);
            }
        } catch (Exception e) {
            log.warn(e.getMessage());
        }
        if (day == null) {
            day = LocalDate.now();
        }
        String mobileDs = MySqlUtils.dsNameSuffix(user.getMobile());
        Vip vip = vip(mobileDs, false);
        set(user, vip, day);
    }

    public List<String> ds(String mobile) {
        if (Utils.isBlank(mobile) || !mobile.matches(UserController.PATTERN_MOBILE)) {
            return Collections.emptyList();
        }
        if (enableVip) {
            List<String> dsNames = vipDao.findByMobile(NumberUtils.toLong(mobile, 10000000000L))
                    .stream().map(Vip::getMobileDs).map(mobileDs -> {
                        int pos = mobileDs.indexOf('@');
                        return pos == -1 ? null : mobileDs.substring(pos + 1);
                    }).filter(ds -> Utils.isNotBlank(ds)).collect(Collectors.toList());
            if (dsNames.size() > 0) {
                return dsNames;
            }
        }
        String ds = DsConfig.ds(mobile);
        if (Utils.isNotBlank(ds)) {
            return Arrays.asList(ds);
        }
        return AppConfig.allowAutoNewDs ? Collections.singletonList(mobile) : Collections.emptyList();
    }

    public List<Vip> list(LocalDate now, Integer days) {
        now = now == null ? LocalDate.now() : now;
        days = days == null ? daysVip : days;
        return enableVip ? vipDao.findByVipDay(now.plusDays(days)) : Collections.emptyList();
    }
}
